js 引用类型

引用类型

  • 使用对象
  • 创建并操作数组
  • 理解基本的JavaScript类型
  • 使用基本类型和基本包装类型

    1.1 Object类型

    ==创建Object实例的方式有两种==。
  • 第一种是使用 new 操作符后跟 Object 构造函数

    1
    2
    3
    var person = new Object();
    person.name = "Nicholas";
    person.age = 29;
  • 另一种方式是使用对象字面量表示法

    1
    2
    3
    4
    var person = {
    name : "Nicholas",
    age : 29
    };

1.2 Array类型

==创建数组的基本方式有两种==。

  • 第一种是使用Array构造函数

    1
    2
    3
    4
    5
    var colors = new Array();
    var colors = new Array(20);
    var colors = new Array("red", "blue", "green");
    var colors = Array(3); // 创建一个包含 3 项的数组
    var names = Array("Greg"); // 创建一个包含 1 项,即字符串"Greg"的数组
  • 使用数组字面量表示法

    1
    2
    3
    var colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
    var names = []; // 创建一个空数组
    var values = [1,2,]; // 不要这样!这样会创建一个包含 2 或 3 项的数组

1.2.1 检测数组

  • instanceof 操作符
    1
    2
    3
    if (value instanceof Array){
    //对数组执行某些操作
    }

instanceof 操作符的问题在于,它假定只有一个全局执行环境。如果网页中包含多个框架,那实 际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自 不同的构造函数。

  • Array.isArray()
    1
    2
    3
    if (Array.isArray(value)){
    //对数组执行某些操作
    }

这个方法的目的是最终确定某个值到底是不是数组,而不管它是在哪个全局执行环境中创建的。

1.2.2 转换方法

所有对象都具有toLocaleString()、toString()和 valueOf()方法。

  • 调用数组的toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。
  • valueOf()返回的还是数组

数组继承的toLocaleString()、toString()和 valueOf()方法,在默认情况下都会以逗号分隔的字符串的形式返回数组项。而如果使用 join()方法,则可以使用不同的分隔符来构建这个字符串。

1.2.3 栈方法

栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。

ECMAScript为数组专门提供了push()和pop()方法,以便实现类似栈的行为。

  • push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并==返回修改后数组的长度==。
  • pop()方法则从数组末尾移除最后一项,减少数组的 length值,然后==返回移除的项==。

    1.2.4 队列方法

    队列数据结构的访问规则是FIFO(First-In-First-Out, 先进先出)。

结合使用 shift()和push()方法,可以像使 用队列一样使用数组。

同时使用unshift()和pop()方法,可以从相反的方向来模拟队列,即在数组的前端添加项,从数组末端移除项

1.2.5 重排序方法

  • reverse()
  • reverse()方法会反转数组项的顺序
  • sort()
  • sort()方法按升序排列数组项。
  • sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的也是字符串。这种排序方式在很多情况下都不是最佳方案。
    1
    2
    3
    var values = [0, 1, 5, 10, 15];
    values.sort();
    alert(values); //0,1,10,15,5

==解决排序方案:==
sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。

该比较函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数a和b,其返回值如下:

  • 若a小于b,在排序后的数组中a应该出现在 b 之前,则返回一个小于0的值。
  • 若a等于b,则返回 0。
  • 若a大于b,则返回一个大于0的值。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function compare(value1, value2) {
    if (value1 < value2) {
    return -1;
    } else if (value1 > value2) {
    return 1;
    } else {
    return 0;
    }
    }

这个比较函数可以适用于大多数数据类型,只要将其作为参数传递给 sort()方法即可.

1
2
3
var values = [0, 1, 5, 10, 15];
values.sort(compare);
alert(values); //0,1,5,10,15

对于数值类型或者其valueOf()方法会返回数值类型的对象类型,可以使用一个更简单的比较函数。这个函数只要用第二个值减第一个值即可.

1
2
3
function compare(value1, value2){
return value2 - value1;
}

1.2.6 操作方法

  • concat()
  • concat()方法可以基于当前数组中的所有项创建一个新数组。具体来说,这个方法会先创建当前数组一个副本,然后将接收到的参数 添加到这个副本的末尾,最后返回新构建的数组。
  • slice()
  • 它能够基于当前数组中的一或多个项创建一个新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项— —==但不包括结束位置的项==。注意,==slice()方法不会影响原始数组==。
  • 如果结束位置小于起始位置,则返回空数组。

    1
    2
    3
    4
    5
    var colors = ["red", "green", "blue", "yellow", "purple"];
    var colors2 = colors.slice(1);
    var colors3 = colors.slice(1,4);
    alert(colors2); //green,blue,yellow,purple
    alert(colors3); //green,blue,yellow
  • [x] splice()

  • splice()的主要用途是向数组的中部插入项:删除、插入、替换
  • 删除:可以删除任意数量的项,只需指定2个参数:要删除的第一项的位置和要删除的项数。 例如,splice(0,2)会删除数组中的前两项。
  • 插入:可以向指定位置插入任意数量的项,只需提供 3个参数:起始位置、0(要删除的项数)和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。例如,splice(2,0,”red”,”green”)会从当前数组的位置 2 开始插入字符串”red”和”green”。
  • 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起 始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如, splice (2,1,”red”,”green”)会删除当前数组位置 2 的项,然后再从位置 2 开始插入字符串 “red”和”green”。
  • ==splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项(如果没有删除任何 项,则返回一个空数组)。==
  • 示例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var colors = ["red", "green", "blue"];
    var removed = colors.splice(0,1); // 删除第一项
    alert(colors); // green,blue
    alert(removed);//red,返回的数组中只包含一项
    removed = colors.splice(1, 0, "yellow", "orange"); // 从位置 1 开始插入两项
    alert(colors); // green,yellow,orange,blue
    alert(removed); // 返回的是一个空数组
    removed = colors.splice(1, 1, "red", "purple"); // 插入两项,删除一项
    alert(colors); //green,red,purple,orange,blue
    alert(removed); //yellow,返回的数组中只包含一项

1.2.7 位置方法

indexOf()和 lastIndexOf()。这两个方法都接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。

这两个方法都返回要查找的项在数组中的位置,或者在没找到的情况下返回-1

在比较第一个参数与数组中的每一项时,会使用全等操作符。

  • indexOf()
  • indexOf()方法从数组的开头(位置0)开始向后查找
  • lastIndexOf()
  • lastIndexOf()方法可返回一个指定的字符串值==最后出现的位置==,在一个字符串中的指定位置从后向前搜索。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var numbers = [1,2,3,4,5,4,3,2,1];
    alert(numbers.indexOf(4)); //3
    alert(numbers.lastIndexOf(4)); //5
    alert(numbers.indexOf(4, 4)); //5
    alert(numbers.lastIndexOf(4, 4)); //3
    var person = { name: "Nicholas" };
    var people = [{ name: "Nicholas" }];
    var morePeople = [person];
    alert(people.indexOf(person)); //-1
    alert(morePeople.indexOf(person)); //0

1.2.8 迭代方法

以下方法都不会修改数组中的包含的值。

  • every()
  • every():对数组中的每一项运行给定函数,如果该函数对每一项都返回 true,则返回 true
  • some()
  • some():对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。
  • filter()
  • filter():对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组。
  • forEach()
  • forEach():对数组中的每一项运行给定函数。这个方法没有返回值。
  • map()
  • map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

==every()、some()==

1
2
3
4
5
6
7
8
9
10
11
var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
alert(everyResult); //false
var someResult = numbers.some(function(item, index, array){
return (item > 2);
});
alert(someResult); //true

==filter()==

1
2
3
4
5
var numbers = [1,2,3,4,5,4,3,2,1];
var filterResult = numbers.filter(function(item, index, array){
return (item > 2);
});
alert(filterResult); //[3,4,5,4,3]

==map()==

1
2
3
4
5
var numbers = [1,2,3,4,5,4,3,2,1];
var mapResult = numbers.map(function(item, index, array){
return item * 2;
});
alert(mapResult); //[2,4,6,8,10,8,6,4,2]

==forEach()==

1
2
3
4
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
//执行某些操作
});

1.2.9归并方法

这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。传给 reduce()和 reduceRight()的函数接收4 个参数:前一个值、当前值、项的索引和数组对象。

  • reduce()
  • reduce()方法从数组的第一项开始,逐个遍历到最后
  • reduceRight()
  • reduceRight()则从数组的最后一项开始,向前遍历到第一项。
    1
    2
    3
    4
    5
    var values = [1,2,3,4,5];
    var sum = values.reduce(function(prev, cur, index, array){
    return prev + cur;
    });
    alert(sum); //15

第一次执行回调函数,prev 是 1,cur 是 2。第二次,prev 是 3(1 加 2 的结果),cur 是 3(数组 的第三项)。这个过程会持续到把数组中的每一项都访问一遍,最后返回结果。
reduceRight()的作用类似,只不过方向相反而已。

1.3 Date类型

常用的日期方法:

1
2
3
4
5
6
7
8
9
10
11
Date(); // 返回当日的日期和时间。
Data.now();//返回表示调用这个方法时的日期和时间的毫秒数
var myDate=new Date(); //创建日期对象
getTime();//返回 1970 年 1 月 1 日至今的毫秒数。
getFullYear();//从 Date 对象以四位数字返回年份。
getMonth();//从 Date 对象返回月份 (0 ~ 11)。
getDate();//从 Date 对象返回一个月中的某一天 (1 ~ 31)。
getDay();//从 Date 对象返回一周中的某一天 (0 ~ 6)。
getHours();//返回 Date 对象的小时 (0 ~ 23)。
getMinutes();//返回 Date 对象的分钟 (0 ~ 59)。
getSeconds();//返回 Date 对象的秒数 (0 ~ 59)。

1.4 RegExp类型

  • 字面量形式
    1
    var expression = / pattern / flags ; //语法

模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、 向前查找以及反向引用。

每个正则表达式都可带有一或多个标志(flags),用以标明正则表达式的行为。正则表达式的匹配模式支持下列 3 个标志。

  • g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止;
  • i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写;
  • m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模式匹配的项。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /*
    *匹配字符串中所有"at"的实例
    */
    var pattern1 = /at/g;
    /*
    *匹配第一个"bat"或“cat”,不区分大小写
    */
    var pattern2 = /[bc]at/i;
    /* 10
    * 匹配所有以"at"结尾的 3 个字符的组合,不区分大小写
    */
    var pattern3 = /.at/gi;

与其他语言中的正则表达式类似,模式中使用的所有元字符都必须转义。正则表达式中的元字符包括:==( [ { \ ^ $ | ) ? * + .]}==

这些元字符在正则表达式中都有一或多种特殊用途,因此如果想要匹配字符串中包含的这些字符,就必须对它们进行转义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
*匹配第一个“bat”或“cat”,不区分大小写
*/
var pattern1 = /[bc]at/i;
/*
* 匹配第一个" [bc]at",不区分大小写
*/
var pattern2 = /\[bc\]at/i;
/*
* 匹配所有以"at"结尾的 3 个字符的组合,不区分大小写
*/
var pattern3 = /.at/gi;
/*
* 匹配所有".at",不区分大小写
*/
var pattern4 = /\.at/gi;

  • RegExp构造函数形式

它接收两个参数:一个是要匹配的字符串模式,另一个是可选的标志字符串。

1
var pattern2 = new RegExp("[bc]at", "i");

  • RegExp实例方法
  • exec()
  • test()

    1.5 Function类型

    每个函数都是 Function 类型的实例,而且都与其他引用类型一样具有属性和方法。

    1.5.1 函数声明与函数表达式

    解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

    1.5.2 作为值的函数

    因为 ECMAScript中的函数名本身就是变量,所以函数也可以作为值来使用。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function callSomeFunction(someFunction,someArgument){
    return someFunction(someArgument);
    }
    function add10(num){
    return num + 10;
    }
    var result1 = callSomeFunction(add10, 10);
    alert(result1); //20
    function getGreeting(name){
    return "Hello, " + name;
    }
    var result2 = callSomeFunction(getGreeting,"Nicholas");
    alert(result2); //"Hello, Nicholas"

callSomeFunction()函数是通用的,即无论第一个参数中传递进来的是什么函数,它都会返回执行第一个参数后的结果。

1.5.3 函数内部属性

在函数内部,有两个特殊的对象:arguments 和 this。
虽然arguments的主要用途是保存函数参数,但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。

1
2
3
4
5
6
7
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}

定义阶乘函数一般都要用到递归算法;如上面的代码所示,在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为了消除这种紧密耦合的现象,可以像下面这样使用 arguments.callee。

1
2
3
4
5
6
7
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}

在这个重写后的factorial()函数的函数体内,没有再引用函数名 factorial。这样,无论引用函数时使用的是什么名字,都可以保证正常完成递归调用。

1
2
3
4
5
6
var trueFactorial = factorial;
factorial = function(){
return 0;
};
alert(trueFactorial(5)); //120
alert(factorial(5)); //0

在此,变量 trueFactorial获得了factorial的值,实际上是在另一个位置上保存了一个函数的指针。然后,我们又将一个简单地返回0的函数赋值给factorial变量。如果像原来的 factorial() 那样不使用arguments.callee,调用 trueFactorial()就会返回0。可是,在解除了函数体内的代 码与函数名的耦合状态之后,trueFactorial()仍然能够正常地计算阶乘;至于factorial(),它现在只是一个返回 0 的函数。

this 引用的是函数据以执行的环境对象——或者也可以说是 this 值(当在网页的全局作用域中调用函数时, this 对象引用的就是 window)。

1
2
3
4
5
6
7
8
window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
sayColor(); //"red"
o.sayColor = sayColor;
o.sayColor(); //"blue"

1.5.4 函数属性和方法

每个函数都包含两个属性:length和prototype。其中,length 属性表示函数希望接收的命名参数的个数。

1
2
3
4
function sum(num1, num2){
return num1 + num2;
}
alert(sum.length); //2

prototype 是保存它们所有实例方法的真正所在。换句话说,诸如 toString()和 valueOf()等方法实际上都保存在 prototype 名下,只不过是通过各自对象的实例访 问罢了。在创建自定义引用类型以及实现继承时,prototype 属性的作用是极为重要的。在ECMAScript5中,prototype 属性是不可枚举的,因此使用 for-in 无法发现。

每个函数都包含两个非继承而来的方法:apply()和 call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。

call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于call()方法而言,第一个参数是 this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()方法时,传递给函数的参数必须逐个列举出来

1
2
3
4
5
6
7
function sum(num1, num2){
return num1 + num2;
}
function callSum(num1, num2){
return sum.call(this, num1, num2);
}
alert(callSum(10,10)); //20

在使用 call()方法的情况下,callSum()必须明确地传入每一个参数。结果与使用apply()没有什么不同。至于是使用 apply()还是call(),完全取决于你采取哪种给函数传递参数的方式最方便。 如果你打算直接传入 arguments 对象,或者包含函数中先接收到的也是一个数组,那么使用 apply() 肯定更方便;否则,选择 call()可能更合适。

传递参数并非 apply()和call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。

1
2
3
4
5
6
7
8
9
window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue

ECMAScript 5 还定义了一个方法:bind()。这个方法会创建一个函数的实例,其 this 值会被绑 定到传给 bind()函数的值。

1
2
3
4
5
6
7
window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue

1.5.6 基本包装类型

为了便于操作基本类型值,ECMAScript 还提供了 3 个特殊的引用类型:Boolean、Number 和 String。

==每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们 能够调用一些方法来操作这些数据。==

1
2
3
var s1 = "some text";
var s2 = s1.substring(2);
s2; // "me text"

基本类型值不是对象,因而从逻辑上讲它们不应该有方法。其实,为了让我们实现这种直观的操作, 后台已经自动完成了一系列的处理。

  • 创建 String 类型的一个实例;
  • 在实例上调用指定的方法;
  • 销毁这个实例。

可以将以上三个步骤想象成是执行了下列 ECMAScript 代码。

1
2
3
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;

引用类型与基本包装类型的主要区别就是对象的生存期。使用 new 操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。来看下面的例子:

1
2
3
var s1 = "some text";
s1.color = "red";
alert(s1.color); //undefined

Boolean类型

Boolean 类型的实例重写了valueOf()方法,返回基本类型值 true 或 false;重写了 toString() 方法,返回字符串”true”和”false”。可是,Boolean 对象在 ECMAScript 中的用处不大,因为它经 常会造成人们的误解。其中最常见的问题就是在布尔表达式中使用 Boolean 对象。

1
2
3
4
5
6
7
var falseObject = new Boolean(false);
var result = falseObject && true;
alert(result); //true
var falseValue = false;
result = falseValue && true;
alert(result); //false

基本类型与引用类型的布尔值还有两个区别。首先,typeof 操作符对基本类型返回”boolean”,而对引用类型返回”object”。其次,由于Boolean对象是 Boolean 类型的实例,所以使用instanceof操作符测试 Boolean对象会返回true,而测试基本类型的布尔值则返回 false。

1
2
3
4
alert(typeoffalseObject); //object
alert(typeof falseValue); //boolean
alert(falseObject instanceof Boolean);//true
alert(falseValue instanceof Boolean);//false

建议是永远不要使 用 Boolean 对象。

Number类型

Number 类型也重写了valueOf()、toLocaleString()和 toString()方法。重写后的valueOf()方法返回对象表示的基本类型的数值,另外两个方法则返回字符串形式的数值。

可以为 toString()方法传递一个表示基数的参数,告诉它返回几进制数值的字符串形式

1
2
3
4
5
6
var num = 10;
alert(num.toString()); //"10"
alert(num.toString(2)); //"1010"
alert(num.toString(8)); //"12"
alert(num.toString(10)); //"10"
alert(num.toString(16)); //"a"

除了继承的方法之外,Number类型还提供了一些用于将数值格式化为字符串的方法。其中,toFixed()方法会按照指定的小数位返回数值的字符串表示

1
2
var num = 10;
alert(num.toFixed(2)); //"10.00"

我们仍 然不建议直接实例化Number类型,而原因与显式创建Boolean对象一样。具体来讲,就是在使用 typeof 和instanceof操作符测试基本类型数值与引用类型数值时,得到的结果完全不同。

String类型

String 对象的方法也可以在所有基本的字符串值中访问到。其中,继承的 valueOf()、toLocale- String()和 toString()方法,都返回对象所表示的基本字符串值。

String 类型的每个实例都有一个length属性,表示字符串中包含多个字符。

String 类型提供了很多方法,用于辅助完成对 ECMAScript中字符串的解析和操作.

1. 字符方法

两个用于访问字符串中特定字符的方法是:charAt()和 charCodeAt()。

1
2
3
4
5
var stringValue = "hello world";
alert(stringValue.charAt(1)); //"e"
var stringValue = "hello world";
alert(stringValue.charCodeAt(1));//输出"101"

2. 字符串操作方法
  • concat()
  • 用于将一或多个字符串拼接起来,返回拼接得到的新字符串.()

    1
    2
    3
    4
    var stringValue = 'hello ';
    var result = stringValue.concat('world');
    alert(result); // 'hello world'
    alert(stringValue); // 'hello '
  • [x] slice()、substr()和 substring()

  • 它们只是返回一个基本类型的字符串值,对原始字符串没有任何影响

    1
    2
    3
    4
    5
    6
    7
    var stringValue = "hello world";
    alert(stringValue.slice(3));//"lo world"
    alert(stringValue.substring(3));//"lo world"
    alert(stringValue.substr(3));//"lo world"
    alert(stringValue.slice(3, 7));//"lo w"
    alert(stringValue.substring(3,7));//"lo w"
    alert(stringValue.substr(3, 7));//"lo worl"
  • 在传递给这些方法的参数是负值的情况下,它们的行为就不尽相同了。其中,slice()方法会将传 入的负值与字符串的长度相加,substr()方法将负的第一个参数加上字符串的长度,而将负的第二个 参数转换为 0。最后,substring()方法会把所有负值参数都转换为 0。

    1
    2
    3
    4
    5
    6
    7
    var stringValue = "hello world";
    alert(stringValue.slice(-3));//"rld"
    alert(stringValue.substring(-3));//"hello world"
    alert(stringValue.substr(-3));//"rld"
    alert(stringValue.slice(3, -4));//"lo w"
    alert(stringValue.substring(3, -4));//"hel"
    alert(stringValue.substr(3, -4));//""(空字符串)
3. 字符串位置方法
  • indexOf()和lastIndexOf()
  • 从一个字符串中搜索给定的子字符串,然后返子字符串的位置(如果没有找到该子字符串,则返回-1)。这两个方法的区别在于:indexOf()方法从字符串的开头向后搜索子字符串,而lastIndexOf()方法是从字符串的末尾向前搜索子字符串.
    1
    2
    3
    var stringValue = "hello world";
    alert(stringValue.indexOf("o"));//4
    alert(stringValue.lastIndexOf("o"));//7
1
2
3
var stringValue = "hello world";
alert(stringValue.indexOf("o", 6));//7
alert(stringValue.lastIndexOf("o", 6)); //4
4. trim()方法
  • ECMAScript5为所有字符串定义了trim()方法。这个方法会创建一个字符串的副本,删除前置及 后缀的所有空格,然后返回结果.
    1
    2
    3
    4
    var stringValue = " hello world ";
    var trimmedStringValue = stringValue.trim();
    alert(stringValue);//" hello world "
    alert(trimmedStringValue);//"hello world"
5. 字符串大小写转换方法

ECMAScript 中涉及字符串大小写转换的方法有 4 个:toLowerCase()、toLocaleLowerCase()、toUpperCase()和 toLocaleUpperCase()。其中,toLowerCase()和toUpperCase()是两个经典的方法,toLocaleLowerCase()和toLocaleUpperCase()方法则是针对特定地区的实现.

6. split()

这个方法可以基于指定的分隔符将一个字符串分割成 多个子字符串,并将结果放在一个数组中。分隔符可以是字符串,也可以是一个RegExp对象(这个方 法不会将字符串看成正则表达式)。split()方法可以接受可选的第二个参数,用于指定数组的大小,以便确保返回的数组不会超过既定大小。

1
2
3
4
var colorText = "red,blue,green,yellow";
var colors1 =colorText.split(","); //['red','blue', 'green', 'yellow']
var colors2 = colorText.split(",", 2); //["red", "blue"]
var colors3 = colorText.split(/[^\,]+/); //["", ",", ",", ",", ""]

1.5.7 单体内置对象

ECMA-262 对内置对象的定义是:“由 ECMAScript 实现提供的、不依赖于宿主环境的对象,这些对 象在 ECMAScript程序执行之前就已经存在了。”意思就是说,开发人员不必显式地实例化内置对象,因为它们已经实例化了。前面我们已经介绍了大多数内置对象,例如 Object、Array 和 String。
ECMA-262还定义了两个单体内置对象:Global 和 Math。

1. Global对象

ECMAScript中的Global对象在某种意义上是作为一个终极的“兜底儿对象”来定义的.

isNaN()、isFinite()、parseInt()以及parseFloat(),实际上全都是Global对象的方法。除此之外,Global 对象还包含其他一些方法。

  • URI 编码方法
  • encodeURI()和encodeURIComponent()方法可以对 URI(UniformResourceIdentifiers,通用资源标识符)进行编码,以便发送给浏览器。有效的 URI 中不能包含某些字符,例如空格。而这两个 URI 编码方法就可以对URI进行编码,它们用特殊的 UTF-8 编码替换所有无效的字符,从而让浏览器能够接受和理解。
  • encodeURI()主要用于整个URI,而encodeURIComponent()主要用于对 URI 中的某一段进行编码。
  • encodeURI()不会对本身属于URI的特殊字符进行编码,例如冒号、正斜杠、问号和井字号;而encodeURIComponent()则会对它发现的任何非标准字符进行编码。
    1
    2
    3
    4
    5
    6
    var uri = "http://www.wrox.com/illegalvalue.htm#start";
    // "http://www.wrox.com/illegal%20value.htm#start"
    alert(encodeURI(uri));
    // "http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"
    alert(encodeURIComponent(uri));

使用 encodeURI()编码后的结果是除了空格之外的其他字符都原封不动,只有空格被替换成了 %20。而 encodeURIComponent()方法则会使用对应的编码替换所有非字母数字字符。这也正是可以 对整个 URI 使用encodeURI(),而只能对附加在现有 URI 后面的字符串使用 encodeURIComponent() 的原因所在。

一般来说,我们使用 encodeURIComponent()方法的时候要比使用 encodeURI()更多,因为在实践中更常见的是对查询字符串参数而不是对基础 URI 进行编码。

与 encodeURI()和encodeURIComponent()方法对应的两个方法分别是decodeURI()和decodeURIComponent()。

  • eval()方法
  • eval() 方法就像是一个完整的ECMAScript解析器,它只接受一个参数,即要执行的ECMAScript(或JavaScript) 字符串。

    1
    2
    3
    eval("alert('hi')");
    相当于
    alert("hi");
  • [x] Global 对象的属性

  • 特殊的值undefined、NaN 以及 Infinity 都是 Global 对象的属性。此外,所有原生引用类型的构造函数,像 Object 和Function,也都是Global 对象的属性。Global对象的所有属性:
  • undefined、NaN、Infinity、Object、Array、Function、Boolean、String、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
  • window对象
  • ECMAScript虽然没有指出如何直接访问 Global 对象,但 Web 浏览器都是将这个全局对象作为 window 对象的一部分加以实现的。因此,在全局作用域中声明的所有变量和函数,就都成为了window 对象的属性。

    2. Math对象

  • [x] min()和 max()方法

    1
    2
    3
    4
    var max = Math.max(3, 54, 32, 16);
    alert(max); //54
    var min = Math.min(3, 54, 32, 16);
    alert(min); //3
  • 在数组中找出最大值或最小值,使用apply()方法

    1
    2
    var arr = [1,2,3,4,5,6,7];
    var max = Math.max.apply(Math, arr);

这个技巧的关键是把Math对象作为apply()的第一个参数,从而正确地设置 this 值。然后,可 以将任何数组作为第二个参数。

  • 舍入方法

下面来介绍将小数值舍入为整数的几个方法:Math.ceil()、Math.floor()和Math.round()。这三个方法分别遵循下列舍入规则:

  • Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;
  • Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;
  • Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    alert(Math.ceil(25.9)); //26
    alert(Math.ceil(25.5)); //26
    alert(Math.ceil(25.1)); //26
    alert(Math.round(25.9)); //26
    alert(Math.round(25.5)); //26
    alert(Math.round(25.1)); //25
    alert(Math.floor(25.9)); //25
    alert(Math.floor(25.5)); //25
    alert(Math.floor(25.1)); //25
  • [x] random()方法

Math.random()方法返回大于等于 0 小于 1 的一个随机数。对于某些站点来说,这个方法非常实用,因为可以利用它来随机显示一些名人名言和新闻事件。套用下面的公式,就可以利用Math.random() 从某个整数范围内随机选择一个值。

==值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)==

公式中用到了 Math.floor()方法,这是因为 Math.random()总返回一个小数值。而用这个小数 值乘以一个整数,然后再加上一个整数,最终结果仍然还是一个小数。举例来说,如果你想选择一个 1 到 10 之间的数值,可以像下面这样编写代码:

1
var num = Math.floor(Math.random() * 10 + 1);

总共有 10 个可能的值(1到10),而第一个可能的值是1。而如果想要选择一个介于 2 到 10 之间的值,就应该将上面的代码改成这样:
var num = Math.floor(Math.random() * 9 + 2);

从 2 数到 10 要数9个数,因此可能值的总数就是 9,而第一个可能的值就是 2。多数情况下,其实 都可以通过一个函数来计算可能值的总数和第一个可能的值

1
2
3
4
5
6
function selectFrom(lowerValue, upperValue) {
var choices = upperValue - lowerValue + 1;
return Math.floor(Math.random() * choices + lowerValue);
}
var num = selectFrom(2, 10);
alert(num); // 介于2和10之间(包括2和10)的一个数值

从数组中随机 取出一项

1
2
3
var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
var color = colors[selectFrom(0, colors.length-1)];
alert(color);//可能是数组中包含的任何一个字符串

  • 其他方法(略)

小结

对象在JavaScript中被称为引用类型的值,而且有一些内置的引用类型可以用来创建特定的对象, 现简要总结如下:

  • 引用类型与传统面向对象程序设计中的类相似,但实现不同
  • Object是一个基础类型,其他所有类型都从 Object继承了基本的行为;
  • Array 类型是一组值的有序列表,同时还提供了操作和转换这些值的功能;
  • Date 类型提供了有关日期和时间的信息,包括当前日期和时间以及相关的计算功能;
  • RegExp类型是ECMAScript支持正则表达式的一个接口,提供了最基本的和一些高级的正则表 达式功能。

函数实际上是Function类型的实例,因此函数也是对象;而这一点正是JavaScript最有特色的地方。由于函数是对象,所以函数也拥有方法,可以用来增强其行为。

因为有了基本包装类型,所以JavaScript中的基本类型值可以被当作对象来访问。三种基本包装类 型分别是:Boolean、Number和String。以下是它们共同的特征:

  • 每个包装类型都映射到同名的基本类型;
  • 在读取模式下访问基本类型值时,就会创建对应的基本包装类型的一个对象,从而方便了数据操作;
  • 操作基本类型值的语句一经执行完毕,就会立即销毁新创建的包装对象。

在所有代码执行之前,作用域中就已经存在两个内置对象:Global 和 Math。在大多数 ECMAScript 实现中都不能直接访问 Global 对象;不过,Web 浏览器实现了承担该角色的 window 对象。全局变 量和函数都是 Global 对象的属性。Math 对象提供了很多属性和方法,用于辅助完成复杂的数学计算 任务。

文章目录
  1. 1. 引用类型
    1. 1.1. 1.1 Object类型
    2. 1.2. 1.2 Array类型
      1. 1.2.1. 1.2.1 检测数组
      2. 1.2.2. 1.2.2 转换方法
      3. 1.2.3. 1.2.3 栈方法
      4. 1.2.4. 1.2.4 队列方法
      5. 1.2.5. 1.2.5 重排序方法
      6. 1.2.6. 1.2.6 操作方法
      7. 1.2.7. 1.2.7 位置方法
      8. 1.2.8. 1.2.8 迭代方法
      9. 1.2.9. 1.2.9归并方法
    3. 1.3. 1.3 Date类型
    4. 1.4. 1.4 RegExp类型
    5. 1.5. 1.5 Function类型
      1. 1.5.1. 1.5.1 函数声明与函数表达式
      2. 1.5.2. 1.5.2 作为值的函数
      3. 1.5.3. 1.5.3 函数内部属性
      4. 1.5.4. 1.5.4 函数属性和方法
      5. 1.5.5. 1.5.6 基本包装类型
        1. 1.5.5.1. Boolean类型
        2. 1.5.5.2. Number类型
        3. 1.5.5.3. String类型
          1. 1.5.5.3.1. 1. 字符方法
          2. 1.5.5.3.2. 2. 字符串操作方法
          3. 1.5.5.3.3. 3. 字符串位置方法
          4. 1.5.5.3.4. 4. trim()方法
          5. 1.5.5.3.5. 5. 字符串大小写转换方法
          6. 1.5.5.3.6. 6. split()
      6. 1.5.6. 1.5.7 单体内置对象
        1. 1.5.6.1. 1. Global对象
        2. 1.5.6.2. 2. Math对象
    6. 1.6. 小结
|